package com.thb.pay.service;

import com.thb.pay.api.agent.vo.resp.AgentChannelVo;
import com.thb.pay.api.merchant.vo.resp.MchInfoVo;
import com.thb.pay.api.merchant.vo.resp.MchPayChannelVo;
import com.thb.pay.api.order.vo.req.PayOrderReq;
import com.thb.pay.api.payment.vo.resp.CurrencyTypeVo;
import com.thb.pay.api.payment.vo.resp.PayChannelAccountVo;
import com.thb.pay.api.payment.vo.resp.PayProductVo;
import com.thb.pay.channel.IPaymentService;
import com.thb.pay.comm.utils.PaymentResult;
import com.thb.pay.core.exception.RRException;
import com.thb.pay.core.utils.IdWorker;
import com.thb.pay.exception.PaymentGatewayEnum;
import com.thb.pay.web.vo.CreateOrderVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

/**
 * @Description 订单服务
 * @Author lucky
 * @data 2019/10/19 15:02
 */
@Slf4j
@Component
public class OrderService extends BaseValidService {

    @Autowired
    private CountProfitServiceSender countProfitServiceSender;

    public PaymentResult createOrder(CreateOrderVo createOrderVo) {
        //1.参数、风控校验
        PayOrderReq payOrder = this.riskCheckReq(createOrderVo);

        IPaymentService paymentService = paymentServiceMap.get(getPaymentChannelNameService(payOrder.getChannelId()));
        if (paymentService == null) {
            throw RRException.build(PaymentGatewayEnum.SYSTEM_ERROR, String.format("支付渠道类型[channelId=%s]实例化异常", payOrder.getChannelId()));
        }
        //支付通道要求的订单格式
        String orderNumber = paymentService.generateOrderNumber(payOrder);
        //通道支持的货币转化
        Long exchangeMoney = paymentService.currencyExchange(payOrder);
        if (StringUtils.isNotBlank(orderNumber)) {
            payOrder.setOrderNum(orderNumber);
        }
        if (exchangeMoney != null) {
            if (exchangeMoney > 0) {
                payOrder.setAmount(exchangeMoney);
            } else {
                throw RRException.build(PaymentGatewayEnum.PASSAGE_UNABLE_MONEY_ERROR);
            }
        }
        //2.下单
        payOrderServiceApi.add(payOrder);
        //3.分润计算统计[支付成功回调后统一处理]
        countProfitServiceSender.sendCountProfitByOrderNum(payOrder.getOrderNum());
        //4.支付下单
        PaymentResult paymentResult = paymentService.payOrder(payOrder);
        return paymentResult;
    }

    public PayOrderReq riskCheckReq(CreateOrderVo createOrderVo) {

        //1.商户规则校验
        MchInfoVo merchantInfo = this.validMerchant(createOrderVo.getMchId());
        //2.校验 appId
        this.validMerchantApp(createOrderVo.getAppId());
        //3.校验 产品ID
        PayProductVo payProduct = this.validProduct(createOrderVo.getProductId());
        //4.校验 货币类型
        CurrencyTypeVo currencyTypeVo = this.validCurrency(createOrderVo.getCurrency());
        //5.校验 金额格式
        Long money = this.validMoney(createOrderVo.getMoney());
        //6.检验 并获取 商户对应产品ID 对应的支付通道配置
        MchPayChannelVo mchPayChannel = this.validMerchantPayChannel(createOrderVo.getMchId(), createOrderVo.getProductId());
        //7.获取支付通道账户 + 通道 风控校验
        PayChannelAccountVo payChannelAccount = this.getPayChannelAccount(mchPayChannel, currencyTypeVo, money, createOrderVo.getChannelAccountId());

        //8.获取商户对应代理商费率
        BigDecimal parentAgentRate = BigDecimal.ZERO;
        BigDecimal agentRate = BigDecimal.ZERO;

        //处理商户代理商费率 【系统仅有商户上两层有对应分润】
        if (merchantInfo.getAgentId() != null) {
            AgentChannelVo agentChannelVo = getAgentChannelByAgentId(merchantInfo.getAgentId(), payProduct.getId());
            agentRate = agentChannelVo != null ? (agentChannelVo.getAgentRate() != null ? agentChannelVo.getAgentRate() : BigDecimal.ZERO) : BigDecimal.ZERO;
        }
        //处理商户代理上级代理商
        if (merchantInfo.getParentAgentId() != null) {
            AgentChannelVo agentChannelVo = getAgentChannelByAgentId(merchantInfo.getParentAgentId(), payProduct.getId());
            parentAgentRate = agentChannelVo != null ? (agentChannelVo.getAgentRate() != null ? agentChannelVo.getAgentRate() : BigDecimal.ZERO) : BigDecimal.ZERO;
        }
        //分润 统一独立的业务去处理 需要根据当前用户选择的支付货币类型处理
        PayOrderReq payOrderReq = PayOrderReq.builder()
                .orderNum(IdWorker.getIdStr())
                .appId(createOrderVo.getAppId())
                .mchId(merchantInfo.getId())
                .mchType(merchantInfo.getType())
                .mchOrderNo(createOrderVo.getMchOrderNo())
                .agentId(merchantInfo.getAgentId())
                .parentAgentId(merchantInfo.getParentAgentId())
                .productId(createOrderVo.getProductId())
                .productTypeId(payProduct.getProductTypeId())
                .channelId(payChannelAccount.getChannelId())
                .channelTypeId(payChannelAccount.getChannelTypeId())
                .channelAccountId(payChannelAccount.getId())
                .channelRuleId(payChannelAccount.getChannelRuleId())
                .amount(money)
                .currencyId(currencyTypeVo.getId())
                .clientIp(createOrderVo.getClientIp())
                .device(createOrderVo.getDevice())
                .subject(createOrderVo.getSubject())
                .body(createOrderVo.getBody())
                .extra(createOrderVo.getExtra())
                .thirdMchNo(payChannelAccount.getThirdMchNo())
                .thirdUser(createOrderVo.getExtra())//参数通道特殊校验 交给对应通道参数进行校验 获取
                .thirdRate(payChannelAccount.getThirdRate())
                .agentRate(agentRate)
                .parentAgentRate(parentAgentRate)
                .mchRate(merchantInfo.getMchRate())
                .amount(money)
                .param1(createOrderVo.getParam1())
                .param2(createOrderVo.getParam2())
                .returnUrl(createOrderVo.getReturnUrl())
                .notifyUrl(createOrderVo.getNotifyUrl())
                .build();

        return payOrderReq;
    }


}
